using System;
using System.Collections.Generic;

/// <summary>
/// 以Int Int为例
/// </summary>
// 拉链哈希表测试类
public class ZipperHashTableTest
{
    public static void RunTest()
    {
        ZipperHashTable<int, int> zipperHashTable = new ZipperHashTable<int, int>(10);
        zipperHashTable.SetValue(1, 1);
        zipperHashTable.SetValue(2, 2);
        zipperHashTable.SetValue(3, 3);
        zipperHashTable.SetValue(10, 4);
        zipperHashTable.SetValue(11, 5);
        zipperHashTable.SetValue(12, 6);

        Console.WriteLine("按 Enter 键查看所有值...");
        Console.ReadLine();

        var keys = zipperHashTable.Keys();
        for (int i = 0; i < keys.Count; i++)
        {
            Console.WriteLine($"Key: {keys[i]}, Value: {zipperHashTable.GetValue(keys[i])}");
        }
    }
}
//IEquatabl为了支持相等比较 实现IEquatable<T> 的类型 才能调用GetHashCode()
public class ZipperHashTable<T,K> where T : System.IEquatable<T>{
     //对于拉链法的哈希表来说 需要一个哈希桶组 也就是 一个链表来管理一个Node
    private LinkedList<ZipperNode<T,K>>[] hashTable;

    public ZipperHashTable(int size){
        hashTable = new LinkedList<ZipperNode<T,K>>[size];
    }

    /// <summary>
    /// 这里返回出去的值 是作为哈希桶的逻辑下标的
    /// </summary>
    /// <param name="key"></param>
    /// <returns></returns>
    private int GetHashCode(T key){
        return Math.Abs(key.GetHashCode()) % hashTable.Length;
    }

   public void SetValue(T key, K value){
    int index = GetHashCode(key);
    
    if(hashTable[index] == null){
        hashTable[index] = new LinkedList<ZipperNode<T,K>>();
    }
    
    // 先检查是否已存在该键
    foreach(var node in hashTable[index]){
        if(node.nodeKey.Equals(key)){
            node.nodeValue = value; 
            return;
        }
    }
    
    // 如果不存在，则添加新节点
    hashTable[index].AddLast(new ZipperNode<T,K>(key,value));
}

    public K GetValue(T key){
        int index = GetHashCode(key);
        if(hashTable[index] == null){
            Console.WriteLine("不存在该Key");
            return default(K);
        }
        foreach(var node in hashTable[index]){
            if(node.nodeKey.Equals(key)){
                return node.nodeValue;
            }
        }
        return default(K);
    }

    public void Remove(T key){
        LinkedList<ZipperNode<T,K>> list = hashTable[GetHashCode(key)];
        if(list == null){
            Console.WriteLine("不存在该Key");
            return;
        }
        foreach(var node in list){
            if(node.nodeKey.Equals(key)){
                list.Remove(node);
                return;
            }
        }
        Console.WriteLine("不存在该Key");
    }

    public List<T> Keys(){
        List<T> keys = new List<T>();
        for(int i = 0; i < hashTable.Length; i++){
            var list = hashTable[i];
            if(list == null) continue;
            foreach(var node in list){
                keys.Add(node.nodeKey);
            }
        }
        return keys;
    }
}
public class ZipperNode<T,K>{
    public T nodeKey;
    public K nodeValue;

    public ZipperNode(T key, K value){
        this.nodeKey =key;
        this.nodeValue =value;
    }
}
